from array import array
from random import *

class Framebuffer:
  
  stack = []
    
  def __init__(self):
    stack = []

  def Create(self, w = 800, h = 600):
    try:
      buffer = array('B')
      for i in range(0, w*h*3): buffer.append(0)

      self.stack.append([buffer,w,h,None])

      return len(self.stack) - 1

    except MemoryError: 
      print "ERROR: Create() failed!"
      return -1        
  
  def Register(self, slot, cb):
    if (callable(cb)): self.stack[slot][3] = cb   

  def Process(self, slot):
    #try:
    buffer,w,h,cb = self.stack[slot]
    if (cb == None): return
  
    for line in range(0, h):
      for pixel in range(0, w):
        p = line*w*3 + pixel*3
        ret = cb(pixel,line,p,p+1,p+2,buffer)
    #except:
    #  print "ERROR: Slot was not Process()ed."

  def Write(self, slot, filename = "undefined"):
    try:
      buffer,w,h,cb = self.stack[slot]
        
      f = open("%s.ppm" % filename, "wb")
      f.write("P6\n# this is a comment.\n%i %i\n255\n" % (w,h))
      buffer.tofile(f)
      f.close()
    
    except:
      print "ERROR: WritePPM() failed!"

  def Get(self, slot):
    try: return tuple(stack[slot][1], stack[slot][2]) # (w,h)
    except: return None

# ------------------------------------------------------------------------------
if __name__ == "__main__":

  lastY=-1
  _c=None
  
  colors = []
  
  def CreateSomeRandomColors():
    for i in range(0, 21):
      colors[len(colors):] = [(randint(0,255),randint(0,255),randint(0,255))]
  
  def Lines(x,y,r,g,b,pixel):
    global lastY,_c
    
    if (lastY != y):
      _c = colors[randint(0,20)]
      lastY = y

    pixel[r],pixel[g],pixel[b] = _c[0],_c[1],_c[2]
  
  def Noise(x,y,r,g,b,pixel):
    global _c
    _c = colors[randint(0,20)]
    pixel[r],pixel[g],pixel[b] = _c[0],_c[1],_c[2]
  
  CreateSomeRandomColors()
  
  f = Framebuffer()
  
  slot1 = f.Create(1280,720)
  f.Register(slot1, Lines)
  f.Process(slot1)
  
  slot2 = f.Create()
  f.Register(slot2, Noise)
  f.Process(slot2)
  
  f.Write(slot1, "lines")
  f.Write(slot2, "noise")
